package edu.ustb.aur.controller;

import edu.ustb.aur.assetpackage.Asset;
import edu.ustb.aur.assetpackage.AssetService;
import edu.ustb.aur.chain.Chain;
import edu.ustb.aur.chain.ChainService;
import edu.ustb.aur.chain.interactive.ChainInteractiveService;
import edu.ustb.aur.moldpackage.AbstractMold;
import edu.ustb.aur.myenum.RightEnum;
import edu.ustb.aur.result.Result;
import edu.ustb.aur.userpackage.UserService;
import edu.ustb.shellchainapi.shellchain.command.ShellChainException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import edu.ustb.aur.myenum.ResultCodeEnum;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

/**
 * @author ShiZhe
 * @create 2021-11-15 15:35
 * 资产前后端交互
 */
@Api(tags = "资产控制器")
@RestController
@RequestMapping("asset")
@CrossOrigin
public class AssetController {

    /**
     * 资产服务
     */
    @Resource
    private AssetService assetService;

    /**
     * 货币资产类型
     */
    private Long currency = 110000000L;

    /**
     * 用户类存储服务
     */
    @Autowired
    private UserService userService;

    /**
     * 资产链服务
     */
    @Autowired
    private ChainService chainService;

    /**
     * 资产链
     */
    private ChainInteractiveService chainInteractiveServiceAsset = new ChainInteractiveService("OBJ");

    /**
     * 添加日志对象
     */
    private Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 创建资产
     *
     * @param asset
     *            资产对象，不包含assetId字段，该字段通过链交易获得
     * @return Result
     */
    @ResponseBody
    @ApiOperation(value = "createAsset", notes = "创建资产")
    @PostMapping("createAsset/{contractName}/{contractId}")
    public Result createAsset(@ApiParam(name = "asset", value = "资产对象", required = true) @RequestBody Asset asset,
                              @ApiParam(name = "contractName", value = "contractName", required = false) @PathVariable String contractName,
                              @ApiParam(name = "contractId", value = "contractId", required = false) @PathVariable String contractId) throws ShellChainException {

        System.out.println(asset);

        //上链参数
        HashMap<String, Object> attributes = new HashMap<>();
        // 唯一表示，生成一个hash值
        attributes.put("contractId", contractId);
        // 只给英文
        attributes.put("contractName", contractName);
        attributes.put("asset", asset);
        // 获取链交易id
        String txId = chainInteractiveServiceAsset.sendToChain(
                "18XEZTrTtqQVfDxVafcJoBd37xrtcBvH4Cs4yV", 0, attributes);
        // 测试专用，上链得到交易ID
        log.info("资产创建信息上链后得到的交易id为：" + txId);

        // chain实体类
        boolean contractIdIsExist = chainService.findContractIdIsExist(contractId);
        if (contractIdIsExist) {
            chainService.addContractTxIdList(contractId, txId);
        } else {
            Chain chain = new Chain();
            chain.setContractId(contractId);
            chain.setContractName(contractName);
            ArrayList<String> contractTxIdList = new ArrayList<>();
            contractTxIdList.add(txId);
            chain.setContractTxIdList(contractTxIdList);
            chainService.createChain(chain);
        }

        // 设置assetId
        asset.setAssetId(txId);
        // 创建asset
        if (assetService.createAsset(asset)){
            // 判断是否是货币资产，如果是，增加用户余额
            if (currency.equals(asset.getAssetType())) {
                // 资产权利映射
                AbstractMold mold = assetService.findMold(txId);
                HashMap<String, Double> fromsRightMap = new HashMap<String, Double>(mold.getMoldMap().get(RightEnum.POSSESS_RIGHT).rightMap.size());
                fromsRightMap.putAll(mold.getMoldMap().get(RightEnum.POSSESS_RIGHT).rightMap);
                // 资金转入，用户列表删除资产
                for (String from : fromsRightMap.keySet()) {
                    userService.transferIn(from, asset.getAssetValue() * fromsRightMap.get(from));
                    userService.deleteAssetList(from, txId);
                }
            } else {
                // 资产权利映射
                AbstractMold mold = assetService.findMold(txId);
                Set<RightEnum> rightEnums = mold.getMoldMap().keySet();
                for (RightEnum rightEnum :rightEnums) {
                    HashMap<String, Double> fromsRightMap = new HashMap<String, Double>(mold.getMoldMap()
                            .get(rightEnum).rightMap.size());
                    fromsRightMap.putAll(mold.getMoldMap().get(rightEnum).rightMap);
                    for (String from : fromsRightMap.keySet()) {
                        userService.addAssetList(from, txId);
                    }
                }
                // 测试专用，资产创建成功信息输出
                log.info("资产的创建操作成功！！！");
            }
            return Result.ok();
        }else {
            return Result.fail(Result.build(asset,ResultCodeEnum.FAIL));
        }

    }

    /**
     * 根据资产id获得资产对象
     * @param assetId 资产id
     * @return Result
     */
    @GetMapping("findAsset/{assetId}")
    public Result findAsset(@ApiParam(name = "assetId", value = "资产hash地址", required = true) @PathVariable String assetId) {
        Asset asset = assetService.findAsset(assetId);
        if (asset == null) {
            log.error("查询失败，数据库中无该资产ID："+ assetId);
            return Result.fail(Result.build(null,ResultCodeEnum.DATA_ERROR));
        }
        log.info("资产的查询操作成功，返回的资产对象为："+ asset.toString());
        return Result.ok(asset);
    }

    /**
     * 修改资产
     *
     * @param asset
     *            资产对象
     * @return Result
     */
    @ApiOperation(value = "updateAsset", notes = "修改资产")
    @PostMapping("updateAsset")
    public Result updateAsset(@ApiParam(name = "asset", value = "资产对象", required = true) @RequestBody Asset asset) {
        if (assetService.updateAsset(asset)){
            return Result.ok();
        }else {
            return Result.fail(Result.build(asset,ResultCodeEnum.FAIL));
        }
    }

    /**
     * 删除资产
     *
     * @param assetId
     *            资产链上编号
     * @return Result
     */
    @ApiOperation(value = "deleteAsset", notes = "删除资产")
    @DeleteMapping("deleteAsset/{assetId}")
    public Result deleteAsset(@ApiParam(name = "assetId", value = "资产hash地址", required = true) @PathVariable String assetId) {
        if (assetService.deleteAsset(assetId)){
            return Result.ok();
        }else {
            return Result.fail(Result.build(assetId,ResultCodeEnum.FAIL));
        }
    }

    /**
     * 查询所有资产的所有信息
     * @return
     */
    @ApiOperation(value = "findAllAsset", notes = "查询所有资产的所有信息")
    @GetMapping("findAllAsset")
    public Result findAllAsset() {
        List<Asset> assetList = assetService.list();
        return Result.ok(assetList);
    }
}
